
import numpy as np
import math as m
def step_2_weight_normalize(matrix,weight_list,q):

    m,n=len(matrix),len(matrix[0])
    lis=[]
    for i in range(m):
        li=[]
        for j in range(n):
            u1=(1-(1-matrix[i][j][0][0]**q)**weight_list[j])**(1/q)
            u2=(1-(1-matrix[i][j][0][1]**q)**weight_list[j])**(1/q)
            v1=matrix[i][j][1][0]**weight_list[j]
            v2=matrix[i][j][1][1]**weight_list[j]
            li.append(([u1,u2],[v1,v2]))
        lis.append(li)
    return lis


def get_score_exactvalue(i,q):
    '''

    :param i:广义正交数
    :prem q:
    :return: 得分,精确值
    '''
    score=1/2*(i[0][0]**q+i[0][1]**q-i[1][0]**q-i[1][1]**q)            #得分函数
    exact_value=1/2*(i[0][0]**q+i[0][1]**q+i[1][0]**q+i[1][1]**q)      #精确值函数

    return score,exact_value

def score(IVq_ROF,q):
    a = IVq_ROF[0][0]
    b = IVq_ROF[0][1]
    c = IVq_ROF[1][0]
    d = IVq_ROF[1][1]
    pai1 = (1 - a ** q - c ** q) ** (1 / q)
    pai2 = (1 - b ** q - d ** q) ** (1 / q)
    score = a + b + c + d + m.cos((b - a) * (m.pi / 2)) + m.cos((c - d) * (m.pi / 2)) + m.sin(
        (a - c) * (m.pi / 2)) + m.sin((b - d) * (m.pi / 2)) + pai1 + pai2
    score = (score - 4) / 4
    return score


def compare(element1,element2,q,n):
    '''

    :param element1: 第一个元素
    :param element2: 第二个元素
    :param q:
    :param n:标记变量，取0是该程序返回两数中的较小数
    :return: 较大的元素
    '''
    lis=[element1,element2]
    score1=score(element1,q)
    score2=score(element2,q)

    if score1>score2:
        value=element1
    elif score1<score2:
        value = element2
    else:
        value=element1

    if n==0:

        del lis[lis.index(value)]
        value=lis[0]


    return value

def step_3_get_best_worst(matrix,q):
    '''

    :param matrix: 加权归一化的矩阵
    :param q:
    :return: 正理想与负理想
    '''
    m,n=len(matrix),len(matrix[0])
    max_list=[]
    min_list=[]

    for j in range(n):
        max=matrix[0][j]
        min=matrix[0][j]
        for i in range(m):
            max=compare(max,matrix[i][j],q,1)
            min=compare(min,matrix[i][j],q,0)
        max_list.append(max)
        min_list.append(min)

    return max_list,min_list

def step_4_get_sparation(matrix,max_min_list,q):
    m,n=len(matrix),len(matrix[0])
    s_postive=[]
    s_negative=[]
    for i in range(m):
        sum1=0;sum2=0
        for j in range(n):
            sum1+=(s([matrix[i][j]],[max_min_list[0][j]],q)**2)
            sum2+=(s([matrix[i][j]],[max_min_list[1][j]],q)**2)
        s_postive.append(sum1**(1/2))
        s_negative.append(sum2**(1/2))
    return 1-np.array(s_postive),1-np.array(s_negative)

def TOPSIS(matrix,weight_list,q):
    normalize_matrix=step_2_weight_normalize(matrix,weight_list,q)
    max_min_list=step_3_get_best_worst(normalize_matrix,q)
    sp,sn=step_4_get_sparation(normalize_matrix,max_min_list,q)
    sp=np.array(sp);sn=np.array(sn)
    value_list=(sp/(sn+sp))
    value_list=[i/sum(value_list) for i in value_list]

    return value_list

def s(a_list,b_list,q):
    if len(a_list)!=len(b_list):
        print('两个集合论域错误')
    length = len(a_list)
    sum1=0;sum2=0
    for i in range(length):
        value1=(min(a_list[i][0][0]**q,b_list[i][0][0]**q)+min(a_list[i][0][1]**q,b_list[i][0][1]**q)+
                min((1-a_list[i][1][0]**q),(1-b_list[i][1][0]**q))+min((1-a_list[i][1][1]**q),(1-b_list[i][1][1]**q)))
        value2=(max(a_list[i][0][0]**q,b_list[i][0][0]**q)+max(a_list[i][0][1]**q,b_list[i][0][1]**q)+
                max((1-a_list[i][1][0]**q),(1-b_list[i][1][0]**q))+max((1-a_list[i][1][1]**q),(1-b_list[i][1][1]**q)))
        sum1+=value1
        sum2+=value2
    #final_value=sum1/sum2

    final_value = round(sum1 / sum2,4)
    return final_value

def r(list1):
    length=len(list1)
    li=[]
    for i in range(length):
        li.append([list1[i],i+1])
    li.sort(key=lambda x: x[0], reverse=True)
    #print(li)
    rank=[li[i][1] for i in range(length)]
    print(rank)


class Topsis:
    def __init__(self,matrix,weight_list=[],q=3):
        '''
        function: MABAC决策方法
        :param matrix: 决策矩阵
        :param weight_list: 属性权重
        :param q: q值
        :param gangliang: 成本型或效益型表示，成本型用0表示，效益型用1表示
        '''
        self.q = q
        self.matrix = matrix
        if len(weight_list):
            self.weight_list = weight_list
        else:
            self.weight_list = [1/len(matrix[0]) for i in range(len(matrix[0]))]


    def getResult(self):
        matrix=self.matrix
        weight_list=self.weight_list
        q=self.q
        normalize_matrix = step_2_weight_normalize(matrix, weight_list, q)
        max_min_list = step_3_get_best_worst(normalize_matrix, q)
        sp, sn = step_4_get_sparation(normalize_matrix, max_min_list, q)
        sp = np.array(sp);sn = np.array(sn)
        value_list = (sp / (sn + sp))
        value_list = [i / sum(value_list) for i in value_list]

        return value_list



if __name__=='__main__':
    a1 = [[([0.7, 0.8], [0.2, 0.3]), ([0.5, 0.6], [0.6, 0.7]), ([0.8, 0.9], [0.1, 0.2]), ([0.8, 0.95], [0.1, 0.2])],
          [([0.8, 0.9], [0.1, 0.2]), ([0.5, 0.55], [0.4, 0.5]), ([0.8, 0.9], [0.1, 0.15]), ([0.8, 0.95], [0.1, 0.2])],
          [([0.9, 0.95], [0.1, 0.2]), ([0.5, 0.6], [0.3, 0.4]), ([0.8, 0.85], [0.2, 0.3]), ([0.8, 0.9], [0.1, 0.2])],
          [([0.2, 0.3], [0.7, 0.8]), ([0.4, 0.5], [0.3, 0.4]), ([0.75, 0.8], [0.2, 0.3]), ([0.7, 0.8], [0.2, 0.3])],
          [([0.1, 0.2], [0.8, 0.9]), ([0.2, 0.3], [0.5, 0.6]), ([0.7, 0.85], [0.3, 0.4]), ([0.6, 0.7], [0.2, 0.3])]]
    #print(step_2_weight_normalize(a1,[0.7,0.1,0.1,0.1],4))

    #print(step_3_get_best_worst(a1,4))



    value=Topsis(a1,[0.7,0.1,0.1,0.1],3).getResult()
    print(value)
